package graphics;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.Semaphore;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import thread.Carro;
@SuppressWarnings("serial")
public class Principal extends JFrame implements ActionListener {
	private JPanel janela;
	private JPanel visao;
	private JLabel carroNegNorte;
	private JLabel carroNegNorte2;
	private JLabel carroNegSul;
	private JLabel carroNegSul2;
	private JLabel carroNorte;
	private JLabel carroNortePonte;
	private JLabel carroNorte2;
	private JLabel carroSul;
	private JLabel carroSulPonte;
	/**
	 * @return the carroNortePonte
	 */
	public JLabel getCarroNortePonte() {
		return carroNortePonte;
	}

	/**
	 * @param carroNortePonte the carroNortePonte to set
	 */
	public void setCarroNortePonte(JLabel carroNortePonte) {
		this.carroNortePonte = carroNortePonte;
	}

	/**
	 * @return the carroSulPonte
	 */
	public JLabel getCarroSulPonte() {
		return carroSulPonte;
	}

	/**
	 * @param carroSulPonte the carroSulPonte to set
	 */
	public void setCarroSulPonte(JLabel carroSulPonte) {
		this.carroSulPonte = carroSulPonte;
	}

	private JLabel carroSul2;
	private JButton criar;
	public static Integer listaN = 0;
	public static Integer listaS = 0;
	private Integer listaEsperaN = 0;
	private Integer listaEsperaS = 0;
	private JTextField sentido;
	private JTextField nome;
	private JTextField tempoTravessia;
	private JTextField tempoPermanencia;
	public JTextArea log;
	private JRadioButton b;
	private JRadioButton c;
	public static Semaphore aux = new Semaphore(1);
    public static Semaphore ponte = new Semaphore(1);
    public static Semaphore norte = new Semaphore(10);
    public static Semaphore sul = new Semaphore(10);
    public static Semaphore mutex = new Semaphore(1);
	public HashMap<String, Carro> mapa = new HashMap<String, Carro>();

	public static void main(String[] args) {
		new Principal();
	}

	public Principal() {
		initComponents();
	}

	private void initComponents() {
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setLayout(null);
		janela = new JPanel();
		janela.setLayout(null);
		janela.setBounds(5, 5, 800, 600);
		janela.setVisible(true);

		try {
			visao = new JImagePanel(Principal.class
					.getResource("/pics/ponte.png").toString().substring(5));
		} catch (IOException e) {
			e.printStackTrace();
		}
		visao.setLayout(null);
		visao.setBounds(350, 10, 400, 585);
		visao.setVisible(true);

		ImageIcon i = new ImageIcon(
				Principal.class.getResource("/pics/Carro1N.png"));
		carroNorte = new JLabel(i);
		carroNorte.setText("");
		carroNorte.setVisible(false);
		carroNorte.setBounds(600, 450, 32, 64);
		janela.add(carroNorte);

		ImageIcon iNP = new ImageIcon(
				Principal.class.getResource("/pics/Carro1N.png"));
		carroNortePonte = new JLabel(iNP);
		carroNortePonte.setText("");
		carroNortePonte.setVisible(false);
		carroNortePonte.setBounds(600, 250, 32, 64);
		janela.add(carroNortePonte);

		carroNorte2 = new JLabel();
		carroNorte2.setText("");
		carroNorte2.setVisible(false);
		carroNorte2.setBounds(580, 450, 16, 18);
		janela.add(carroNorte2);

		ImageIcon iNeg = new ImageIcon(
				Principal.class.getResource("/pics/Carro1Neg.png"));
		carroNegNorte = new JLabel(iNeg);
		carroNegNorte.setText("");
		carroNegNorte.setVisible(false);
		carroNegNorte.setBounds(350, 450, 64, 32);
		janela.add(carroNegNorte);

		carroNegNorte2 = new JLabel();
		carroNegNorte2.setText("");
		carroNegNorte2.setVisible(false);
		carroNegNorte2.setFont(new Font("Arial Black", 12, 12));
		carroNegNorte2.setForeground(new Color(2, 0, 20));
		carroNegNorte2.setBounds(360, 490, 10, 16);
		janela.add(carroNegNorte2);

		ImageIcon iSulNeg = new ImageIcon(
				Principal.class.getResource("/pics/Carro1Neg.png"));
		carroNegSul = new JLabel(iSulNeg);
		carroNegSul.setText("");
		carroNegSul.setVisible(false);
		carroNegSul.setBounds(350, 20, 64, 32);
		janela.add(carroNegSul);

		carroNegSul2 = new JLabel();
		carroNegSul2.setText("");
		carroNegSul2.setVisible(false);
		carroNegSul2.setFont(new Font("Arial Black", 12, 12));
		carroNegSul2.setForeground(new Color(255, 255, 255));
		carroNegSul2.setBounds(420, 20, 16, 18);
		janela.add(carroNegSul2);

		ImageIcon i2 = new ImageIcon(
				Principal.class.getResource("/pics/Carro1S.png"));
		carroSul = new JLabel(i2);
		carroSul.setText("");
		carroSul.setVisible(false);
		carroSul.setBounds(580, 20, 33, 66);
		janela.add(carroSul);

		ImageIcon iSP = new ImageIcon(
				Principal.class.getResource("/pics/Carro1S.png"));
		carroSulPonte = new JLabel(iSP);
		carroSulPonte.setText("");
		carroSulPonte.setVisible(false);
		carroSulPonte.setBounds(600, 250, 33, 66);
		janela.add(carroSulPonte);

		carroSul2 = new JLabel();
		carroSul2.setText("");
		carroSul2.setVisible(false);
		carroSul2.setBounds(510, 20, 16, 18);
		janela.add(carroSul2);

		log = new JTextArea();
		log.setText("-----------------LOG------------------");
		log.setBounds(5, 300, 300, 300);
		log.setEditable(false);
		log.setVisible(true);
		janela.add(log);

		janela.add(visao);

		// janela.setComponentZOrder(carroNorte2, 0);
		// janela.setComponentZOrder(carroNorte, 0);
		// janela.setComponentZOrder(visao, 1);

		// FORMULÁRIO

		criar = new JButton("Criar");
		criar.addActionListener(this);
		criar.setActionCommand("criarCarro");
		criar.setBounds(80, 170, 70, 18);
		janela.add(criar);

		JButton matar = new JButton("Matar");
		matar.addActionListener(this);
		matar.setActionCommand("matarCarro");
		matar.setBounds(180, 170, 79, 18);
		janela.add(matar);

		this.setBounds(100, 100, 800, 650);
		this.add(janela);
		this.setVisible(true);
		this.setResizable(false);
		
		b = new JRadioButton();
		b.setText("norte");
		b.addActionListener(this);
		b.setActionCommand("escolherSentidoNorte");
		b.setBounds(180, 90, 100, 16);
		b.setSelected(true);
		janela.add(b);
		
		
		c = new JRadioButton();
		c.setText("sul");
		c.addActionListener(this);
		c.setActionCommand("escolherSentidoSul");
		c.setBounds(180, 120, 100, 16);
		janela.add(c);
		
		sentido = new JTextField();
		sentido.setText("");
		sentido.setBounds(180, 90, 100, 16);
//		janela.add(sentido);

		JLabel lblSentido = new JLabel("Sentido: ");
		lblSentido.setLabelFor(sentido);
		lblSentido.setBounds(10, 90, 80, 16);
		janela.add(lblSentido);

		nome = new JTextField();
		nome.setText("");
		nome.setBounds(180, 5, 100, 16);
		janela.add(nome);

		JLabel lblNome = new JLabel("Nome: ");
		lblNome.setLabelFor(nome);
		lblNome.setBounds(10, 5, 80, 16);
		janela.add(lblNome);

		tempoTravessia = new JTextField();
		tempoTravessia.setText("");
		tempoTravessia.setBounds(180, 30, 100, 16);
		janela.add(tempoTravessia);

		JLabel lbltravessia = new JLabel("Tempo Travessia: ");
		lbltravessia.setLabelFor(tempoTravessia);
		lbltravessia.setBounds(10, 30, 150, 16);
		janela.add(lbltravessia);

		tempoPermanencia = new JTextField();
		tempoPermanencia.setText("");
		tempoPermanencia.setBounds(180, 60, 100, 16);
		janela.add(tempoPermanencia);

		JLabel lblpermanencia = new JLabel("Tempo Permanencia: ");
		lblpermanencia.setLabelFor(tempoPermanencia);
		lblpermanencia.setBounds(10, 60, 150, 16);
		janela.add(lblpermanencia);

		RepaintThread rt = new RepaintThread(janela);
		rt.start();
	}

	public void setListaN(Integer listaN) {
		this.listaN = listaN;
	}

	public void setListaS(Integer listaS) {
		this.listaS = listaS;
	}

	public void setListaEsperaN(Integer listaEsperaN) {
		this.listaEsperaN = listaEsperaN;
	}

	public void setListaEsperaS(Integer listaEsperaS) {
		this.listaEsperaS = listaEsperaS;
	}

	public int getListaEsperaN() {
		return listaEsperaN;
	}

	public void setListaEsperaN(int listaEsperaN) {
		this.listaEsperaN = listaEsperaN;
	}

	public int getListaEsperaS() {
		return listaEsperaS;
	}

	public void setListaEsperaS(int listaEsperaS) {
		this.listaEsperaS = listaEsperaS;
	}

	public JLabel getCarroNegNorte() {
		return carroNegNorte;
	}

	public void setCarroNegNorte(JLabel carroNegNorte) {
		this.carroNegNorte = carroNegNorte;
	}

	public JLabel getCarroNegNorte2() {
		return carroNegNorte2;
	}

	public void setCarroNegNorte2(JLabel carroNegNorte2) {
		this.carroNegNorte2 = carroNegNorte2;
	}

	public JLabel getCarroNegSul() {
		return carroNegSul;
	}

	public void setCarroNegSul(JLabel carroNegSul) {
		this.carroNegSul = carroNegSul;
	}

	public JLabel getCarroNegSul2() {
		return carroNegSul2;
	}

	public void setCarroNegSul2(JLabel carroNegSul2) {
		this.carroNegSul2 = carroNegSul2;
	}

	public JLabel getCarroNorte() {
		return carroNorte;
	}

	public void setCarroNorte(JLabel carroNorte) {
		this.carroNorte = carroNorte;
	}

	public JLabel getCarroNorte2() {
		return carroNorte2;
	}

	public void setCarroNorte2(JLabel carroNorte2) {
		this.carroNorte2 = carroNorte2;
	}

	public JLabel getCarroSul() {
		return carroSul;
	}

	public void setCarroSul(JLabel carroSul) {
		this.carroSul = carroSul;
	}

	public JLabel getCarroSul2() {
		return carroSul2;
	}

	public void setCarroSul2(JLabel carroSul2) {
		this.carroSul2 = carroSul2;
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getActionCommand().equals("criarCarro")) {
			if (b.isSelected()) {
				criarThreadCarroNorte();
			} else {
				criarThreadCarroSul();
			}
		} else if (arg0.getActionCommand().equals("matarCarro")) {
			matarCarro(nome.getText());
		}else if(arg0.getActionCommand().equals("escolherSentidoNorte")){
			setarSentidoNorte();
		}else if(arg0.getActionCommand().equals("escolherSentidoSul")){
			setarSentidoSul();
		}
	}

	private void setarSentidoNorte() {
		b.setSelected(true);
		c.setSelected(false);
	}
	
	private void setarSentidoSul() {
		c.setSelected(true);
		b.setSelected(false);
	}

	private void matarCarro(String nome) {
			Carro c = mapa.get(nome);
			c.morra = true;
			
	}

	public void passandoNaPonte(String sentido, long tempoTravessia) {
		try {
			if (sentido.equals("norte")) {
				if (listaN > 0) {
				} else if (listaN == 0) {
					carroNorte.setVisible(false);
					carroNorte2.setVisible(false);
				} else if (listaN == 1) {
					carroNorte2.setVisible(false);
				} else if (listaN > 1) {
//					carroNorte2.setVisible(true);
//					carroNorte2.setText(listaN + "");
				}
				long tempoIni = System.currentTimeMillis();
				while ((200 + tempoIni) - System.currentTimeMillis() > 0) {
					
				}
				carroNorte.setVisible(false);
				aux.acquire();
				listaN--;
				listaS++;
				aux.release();
			} else {
				if (listaS > 0) {
				} else if (listaS == 0) {
					carroSul.setVisible(false);
					carroSul2.setVisible(false);
				} else if (listaS == 1) {
					carroSul2.setVisible(false);
				} else if (listaS > 1) {
//					carroSul2.setVisible(true);
//					carroSul2.setText(listaS + "");
				}
				long tempoIni = System.currentTimeMillis();
				while ((200 + tempoIni) - System.currentTimeMillis() > 0) {
					
				}
				carroSul.setVisible(false);
			}

			long tempoIni = System.currentTimeMillis();
			while ((tempoTravessia + tempoIni) - System.currentTimeMillis() > 0) {
				if (sentido.equals("norte")) {
					if (!carroNortePonte.isVisible()) {
						carroNortePonte.setVisible(true);
					}
					if (System.currentTimeMillis() % 4 == 0) {
						carroNortePonte.setBounds(600, 250, 32, 64);
					} else {
						carroNortePonte.setBounds(600, 255, 32, 64);
					}
				} else {
					if (!carroSulPonte.isVisible()) {
						carroSulPonte.setVisible(true);
					}
					if (System.currentTimeMillis() % 2 == 0) {
						carroSulPonte.setBounds(600, 250, 33, 66);
					} else {
						carroSulPonte.setBounds(600, 255, 33, 66);
					}
				}
			}
			if(sentido.equals("norte")){
				aux.acquire();
				listaN--;
				listaS++;
				aux.release();
			}else{
				aux.acquire();
				listaN++;
				listaS--;
				aux.release();
			}
			if(sentido.equals("norte") && listaN == 0){
				carroNortePonte.setVisible(false);
			}else if(listaS == 0){
				carroSulPonte.setVisible(false);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void cuidandoNaVida(int i, String sentido) {
		if (sentido.equals("norte")) {
			try {
				aux.acquire();
				listaEsperaN++;
				aux.release();
				if (listaEsperaN > 1) {
					carroNegNorte2.setText(listaEsperaN + "");
					carroNegNorte2.setVisible(true);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			try {
				aux.acquire();
				listaEsperaS++;
				aux.release();
				if (listaEsperaS > 1) {
					carroNegSul2.setText(listaEsperaS + "");
					carroNegSul2.setVisible(true);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		long inicio = System.currentTimeMillis();
		while (inicio + (i) - System.currentTimeMillis() >= 0) {
			if (sentido.equals("norte")) {
				if (!carroNegNorte.isVisible()) {
					carroNegNorte.setVisible(true);
				}
				if (System.currentTimeMillis() % 2 == 0) {
					carroNegNorte.setBounds(350, 450, 64, 32);
				} else {
					carroNegNorte.setBounds(350, 445, 64, 32);
				}
			} else {
				if (!carroNegSul.isVisible()) {
					carroNegSul.setVisible(true);
				}
				if (System.currentTimeMillis() % 2 == 0) {
					carroNegSul.setBounds(450, 2, 100, 64);
				} else {
					carroNegSul.setBounds(450, 8, 100, 64);
				}
			}
		}

		if (sentido.equals("norte")) {
			try {
				aux.acquire();
				listaEsperaN--;
				aux.release();
				if (listaEsperaN == 1) {
					carroNegNorte2.setVisible(false);
				} else if (listaEsperaN <= 0) {
					carroNegNorte.setVisible(false);
				} else {
//					carroNegNorte2.setText(listaEsperaN + "");
//					carroNegNorte2.setVisible(true);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} else {
			try {
				aux.acquire();
				listaEsperaS--;
				aux.release();
				if (listaEsperaS == 1) {
					carroNegSul2.setVisible(false);
				} else if (listaEsperaS <= 0) {
					carroNegSul.setVisible(false);
				} else {
//					carroNegSul2.setText(listaEsperaS + "");
//					carroNegSul2.setVisible(true);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void criarThreadCarroNorte() {
		Carro carro = new Carro(nome.getText(), Integer.parseInt(tempoTravessia
				.getText()), "norte", listaN, listaS, this,
				Integer.parseInt(tempoPermanencia.getText()));
		mapa.put(carro.getNome(), carro);
		carro.start();
	}

	private void criarThreadCarroSul() {
		
		Carro carro = new Carro(nome.getText(), Integer.parseInt(tempoTravessia
				.getText()), "sul" , listaN, listaS, this,
				Integer.parseInt(tempoPermanencia.getText()));
		mapa.put(carro.getNome(), carro);
		carro.start();
	}


	public int getListaN() {
		return listaN;
	}

	public void setListaN(int listaN) {
		this.listaN = listaN;
	}

	public int getListaS() {
		return listaS;
	}

	public void setListaS(int listaS) {
		this.listaS = listaS;
	}

	public void apagarLabels(String nome, String sentido) {
		if (sentido.equals("norte")) {
			carroNorte.setVisible(false);
		} else {
			carroSul.setVisible(false);
		}
	}
}